Skip to content

[SDSP-485] Support suppressions for secret rules - #938

Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 4 commits into
mainfrom
vincent.hourdel/secret_suppressions
Sep 24, 2026
Merged

gh-worker-dd-mergequeue-cf854d[bot] merged 4 commits into
mainfrom
vincent.hourdel/secret_suppressions

Conversation

@vhourdel

@vhourdel vhourdel commented Jul 13, 2026 •

Copy link
Copy Markdown
Contributor

What problem are you trying to solve?

Some secrets matched by secret rules aren't actual secrets: they may be test tokens, test card numbers, dummy values, etc.

What is your solution?

Add support for suppressions, which are natively supported by the secret scanning engine already. This allows users to specify "suppressions" which are some kind of filter on top of the matches, to determine whether the match should be kept or not.

@datadog-prod-us1-5

datadog-prod-us1-5 Bot commented Jul 13, 2026 •

Copy link
Copy Markdown

🎯 Code Coverage (details)
• Patch Coverage: 100.00%
• Overall Coverage: 85.67% (+0.06%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 0af2092 | Docs | Give us feedback!

Comment thread crates/secrets/src/model/secret_rule.rs Outdated
exact_match.sort();

digest.push_str(&format!(
":suppressions:{starts_with:?}:{ends_with:?}:{exact_match:?}",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't rely on the formatting of the Debug impl (which is what :? is) to format the contents.

I would use starts_with.join and then use the normal Display impl ({starts_with})

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in a628e91

Comment thread crates/secrets/src/model/secret_rule.rs Outdated
}))
.generate_diff_aware_digest();

assert_ne!(legacy_digest, with_suppressions);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what value this adds. I would remove this test

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in a628e91

Comment thread crates/secrets/src/model/secret_rule.rs Outdated
}

#[test]
fn test_convert_to_sds_ruleconfig_with_suppressions() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test isn't testing anything. You should either have an assertion somewhere or remove the test.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was more or less using the same pattern as the test above to ensure that converting the rule doesn't panic but I agree this is probably not testing much of anything. I'm removing this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in a628e91

}

#[test]
fn test_find_secrets_with_rule_suppressions() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand the point of this test -- could you explain?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test is checking that the built scanner from a SecretRule that has suppressions configured does in fact suppress matches.

Here the pattern would match both lines in the dummy code provided, but the second line has an exact_match in the suppressions that would suppress it. The test makes sure that this is the case and that we indeed match the first line, but not the second.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concern is that the behavior it asserts:

assert_eq!(
    matches.first().unwrap().matches.first().unwrap().start,
    Position { line: 1, col: 1 }
);

Is merely testing that SDS's suppression implementation is correct. That belongs in SDS library tests, not here (and in fact, this is already covered by SDS's test_match_suppression_suppress_half_of_the_matches)

And additionally, we have no test coverage for what new behavior this PR actually introduces -- that build_sds_scanner correctly threads the SecretRule suppressions through to SDS. Hypothetically if we (datadog-static-analyzer) forgot to pass the suppression to SDS, but SDS were to independently omit the second finding for whatever reason, this test would incorrectly pass.

So what we need is a control case. You'd want to test a SecretRule { suppressions: None } and assert assert_eq!(matches[0].matches.len(), 2); and then pass in SecretRule { suppressions: Some(...) } and assert_eq!(matches[0].matches.len(), 1);

And from there we know the delta can only be explained by the change to suppressions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes that's very fair, thank you for the thorough explanation. I've reworked the test in 0af2092 to match the behavior you are proposing.

Comment thread crates/secrets/src/model/secret_rule.rs Outdated
pub exact_match: Vec<String>,
}

impl From<&SecretRuleSuppressions> for dd_sds::Suppressions {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more idiomatic to impl From<SecretRuleSuppressions> and let the caller control cloning if they want to.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, changed in a628e91

@vhourdel
vhourdel marked this pull request as ready for review September 22, 2026 08:04
@vhourdel
vhourdel requested a review from a team as a code owner September 22, 2026 08:04
Copilot AI lite review requested due to automatic review settings September 22, 2026 08:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

No unresolved blocking issues were identified.

Review effort: Lite
Findings: None

What changed in this PR

Adds secret-rule suppressions to exclude configured dummy or test values from secret scanning.

Changes:

  • Adds suppression configuration and SDS conversion.
  • Propagates suppressions through API models and scanning.
  • Updates tests and fixtures.
File Description
crates/​secrets/​src/​scanner.rs Adds suppression behavior coverage.
crates/​secrets/​src/​model/​secret_rule.rs Defines and applies suppressions.
crates/​cli/​src/​sarif/​sarif_utils.rs Updates test rule fixtures.
crates/​cli/​src/​model/​datadog_api.rs Deserializes API suppressions.
crates/​bins/​src/​git_history.rs Updates test fixtures.
crates/​bins/​src/​bin/​datadog_static_analyzer_server/​endpoints.rs Updates server test fixtures.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants